package com.example.service.impl;

import com.example.es.search.common.IndexKey;
import com.example.es.search.model.PostDocument;
import com.example.es.search.repository.PostRepository;
import com.example.service.SearchService;
import com.example.vo.PostVo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;


/**
 * 使用ElasticSearch有两种方法：
 * 1.spring jpa的repository
 * 2.spring的template
 *
 *
 * @Author 林必昭
 * @Date 2019/9/7 11:32
 */
@Slf4j
@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    PostRepository postRepository;

    @Autowired
    ModelMapper modelMapper;

    /**
     * query搜索查询方法逻辑实现
     * @param pageable
     * @param keyword
     * @return
     */
    @Override
    public Page<PostDocument> query(Pageable pageable, String keyword) {

        //多个字段匹配只要满足一个即可返回结果
        MultiMatchQueryBuilder queryBuilder = QueryBuilders.multiMatchQuery(keyword,
                IndexKey.POST_TITLE,
                IndexKey.POST_AUTHOR,
                IndexKey.POST_CATEGORY,
                IndexKey.POST_DESCRIPTION,
                IndexKey.POST_TAGS);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder)
                .withPageable(pageable).build();

        Page<PostDocument> page = postRepository.search(searchQuery);

        log.info("查询- {} -关键字得到的结果如下--------->{}个查询结果，一个{}页",keyword,page.getTotalElements(),page.getTotalPages());
        return page;
    }

    /**
     * 初始化es数据，initEsData的关键是，首先将数据查出来，再通过ModelMapper将PostVo映射成PostDocument
     *
     * @param datas
     * @return
     */
    @Override
    public int initEsData(List<PostVo> datas) {
        if (datas==null || datas.isEmpty()) return 0;

        List<PostDocument> docs = new ArrayList<>();

        for (PostVo vo : datas){
            //调用ModelMapper将对象模型PostVo隐式映射成PostDocument
            PostDocument postDocument = modelMapper.map(vo, PostDocument.class);
            docs.add(postDocument);
        }
        //批量保存
        postRepository.saveAll(docs);
        return docs.size();
    }
}
